#!/usr/bin/env ruby
#
#  Created by Dzema Dmitriy
#  Copyright (c) 2006-2007. All rights reserved.
PROGRAM_VERSION = '0.7b'

$:.push('./lib')
require "rubygems"
require "choice"

require "Logger"
require "Tokenizer"
require "Parser"
require "ParserUtils"
require "Optimizer"
require "CodeGenerator"

def compiler_mode(file, log)
  tok   = Tokenizer.new(file, log)
  pars  = Parser.new(tok, log)
  gen   = CodeGenerator.new(:parrot)
  e1    = pars.parse
#  e1 = Optimizer.Optimize(e)
  str   = gen.generate(e1)
  
  File.open(Choice.choices[:outfile], "w") do |file|
    file << str
  end
end

def tokenizer_mode(file,log)
  tok = Tokenizer.new(file,log)

  while (!(token = tok.next_token).kind_of?(EndFileToken))
    t = tok.get_token
    puts t
    block_given? && yield(t)
  end
end

def parser_mode(file,log)
  tok = Tokenizer.new(file,log)
  
  pars = Parser.new(tok,log)
  begin
    result = pars.parse()
  rescue CompilerException => e
    puts "Error happened: #{e} at <#{e.line},#{e.pos}>"
  else
    if (Choice.choices[:mode] == 'symbols')
      pars.print_sym_tables()
    else
      puts result.to_parenth_notation
    end
  end
end

def main
  log = Logger.new(STDOUT)
  log.datetime_format = "%Y-%m-%d %H:%M:%S "
  log.level = Choice.choices[:log]
  case Choice.choices[:mode]
    when 'tok'
      tokenizer_mode(Choice.choices[:file],log)
    when 'parser'
      parser_mode(Choice.choices[:file],log)
    when 'compiler'
      compiler_mode(Choice.choices[:file],log)
    when 'symbols'
      parser_mode(Choice.choices[:file],log)
  end
end

Choice.options do
    header 'Author: Dmitriy Dzema'

    option :help do
      long '--help'
      desc 'Show this message'
    end
    
    separator ''
    
    option :mode, :required => 1 do
      short '-m'
      long '--mode=[MODE]'
      desc 'Compiler mode: tok,parser,compiler symbols'
      valid %w[tok parser compiler symbols]
      default 'tok'
    end
    
    option :file do
      short '-f'
      long '--file=FILE'
      desc 'Input file'
      default 'test.txt'
    end
    
    option :outfile do
      short '-o'
      long '--outfile=FILE'
      desc 'Path to output file'
      default './out.pir'
    end
    
    option :log do
      short '-l'
      long '--log=[LEVEL]'
      desc 'Log level'
      cast Integer
      default Logger::Severity::INFO
    end
    
    option :version do
        short '-v'
        long '--version'
        desc 'compiler version'
        action do
          puts "compiler version v#{PROGRAM_VERSION}"
        end
    end
end

main()